﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using Autodesk.Revit.DB;
using Gpc;
using HYCodeBase.Math;

namespace HYRevitCode.RevitTopologySuite.GPCAdapter
{
	public class GpcPolygonController
	{
		public static List<List<List<Curve>>> PolygonToArarCurve(IPolygon intPolygon)
		{
			GraphicsPath graphicsPath = intPolygon.ToGraphicsPath(ContourType.Filled, GraphicsPathType.Lines);
			GraphicsPath graphicsPath2 = intPolygon.ToGraphicsPath(ContourType.Hollow, GraphicsPathType.Lines);
			PointF[] array = null;
			bool flag = true;
			try
			{
				array = graphicsPath.PathPoints;
			}
			catch
			{
				flag = false;
			}
			PointF[] array2 = null;
			bool flag2 = true;
			try
			{
				array2 = graphicsPath2.PathPoints;
			}
			catch
			{
				flag2 = false;
			}
			int num = 0;
			if (flag)
			{
				num += array.Count<PointF>();
			}
			if (flag2)
			{
				num += array2.Count<PointF>();
			}
			PointF[] array3 = new PointF[num];
			if (flag)
			{
				for (int i = 0; i < array.Count<PointF>(); i++)
				{
					array3[i] = new PointF(array[i].X, array[i].Y);
				}
			}
			if (flag2)
			{
				for (int j = array.Count<PointF>(); j < num; j++)
				{
					array3[j] = new PointF(array2[j - array.Count<PointF>()].X, array2[j - array.Count<PointF>()].Y);
				}
			}
			List<List<List<Curve>>> result = null;
			if (flag)
			{
				result = GpcPolygonController.ConvertPointToAreaCurves(array3);
			}
			return result;
		}

		public static Polygon ConstructPolygon(List<Curve> lstInputShellCurves, List<List<Curve>> lstlstHolCurves = null)
		{
			Polygon polygon = null;
			polygon = new Polygon();
			Polygon result;
			try
			{
				List<XPoint2D> list = new List<XPoint2D>();
				if (lstInputShellCurves == null)
				{
					result = null;
				}
				else
				{
					list = GpcPolygonController.GetCurvePointsForGPC(lstInputShellCurves);
					if (list.Count > 2)
					{
						polygon.AddContour(list.ToArray(), false);
					}
					if (lstlstHolCurves != null)
					{
						foreach (List<Curve> lstInputCurves in lstlstHolCurves)
						{
							list = GpcPolygonController.GetCurvePointsForGPC(lstInputCurves);
							if (list.Count > 2)
							{
								polygon.AddContour(list.ToArray(), true);
							}
						}
					}
					result = polygon;
				}
			}
			catch (Exception)
			{
				result = polygon;
			}
			return result;
		}

		public static List<XYZ> CompressPoints(List<XPoint2D> pts)
		{
			List<XYZ> list = new List<XYZ>();
			if (pts.Count > 1)
			{
				list.Add(new XYZ(pts[0].X, pts[0].Y, 0.0));
				for (int i = 1; i < pts.Count; i++)
				{
					XYZ xyz = list[list.Count - 1];
					XYZ xyz2 = new XYZ(pts[i].X, pts[i].Y, 0.0);
					if (xyz2.DistanceTo(xyz) >= 1E-10)
					{
						list.Add(xyz2);
					}
				}
			}
			return list;
		}

		public static List<XPoint2D> GetPolygonPoints(Polygon input, ContourType inputType)
		{
			List<XPoint2D> list = new List<XPoint2D>();
			try
			{
				XPoint2DList[] array = input.ToXPolygon(inputType);
				for (int i = 0; i < array.Length; i++)
				{
					foreach (XPoint2D item in array[i].Vertex)
					{
						list.Add(item);
					}
				}
			}
			catch (Exception)
			{
			}
			return list;
		}

		public static List<List<Curve>> ConvertPointToAreaCurves(List<XPoint2D> pts)
		{
			if (pts.Count > 1)
			{
				pts.Add(pts[0]);
			}
			List<XYZ> list = GpcPolygonController.CompressPoints(pts);
			List<XYZ> list2 = new List<XYZ>();
			List<List<XYZ>> list3 = new List<List<XYZ>>();
			for (int i = 0; i < list.Count; i++)
			{
				if (GpcPolygonController.IsExistPoint(list2, list[i]) && i == list.Count - 1)
				{
					List<XYZ> list4 = GpcPolygonController.CompressPointForCurve(list2);
					if (list4.Count > 2)
					{
						list3.Add(list4);
					}
					list2 = new List<XYZ>();
				}
				else
				{
					list2.Add(list[i]);
				}
			}
			List<List<Curve>> list5 = new List<List<Curve>>();
			foreach (List<XYZ> list6 in list3)
			{
				List<Curve> list7 = new List<Curve>();
				for (int j = 0; j < list6.Count; j++)
				{
					int index = (j + 1) % list6.Count;
					XYZ xyz = new XYZ(list6[j].X, list6[j].Y, 0.0);
					XYZ xyz2 = new XYZ(list6[index].X, list6[index].Y, 0.0);
					Curve item = Line.CreateBound(xyz, xyz2);
					list7.Add(item);
				}
				list5.Add(list7);
			}
			return list5;
		}

		private static List<List<List<Curve>>> ConvertPointToAreaCurves(PointF[] pts)
		{
			List<List<XYZ>> list = GpcPolygonController.DivPoints(GpcPolygonController.CompressPoints(pts));
			List<List<List<XYZ>>> list2 = new List<List<List<XYZ>>>();
			foreach (List<XYZ> list3 in list)
			{
				List<XYZ> list4 = new List<XYZ>();
				List<List<XYZ>> list5 = new List<List<XYZ>>();
				foreach (XYZ xyz in list3)
				{
					if (GpcPolygonController.IsExistPoint(list4, xyz))
					{
						List<XYZ> list6 = GpcPolygonController.CompressPointForCurve(list4);
						if (list6.Count > 2)
						{
							list5.Add(list6);
						}
						list4 = new List<XYZ>();
					}
					else
					{
						list4.Add(xyz);
					}
				}
				list2.Add(list5);
			}
			List<List<List<Curve>>> list7 = new List<List<List<Curve>>>();
			foreach (List<List<XYZ>> list8 in list2)
			{
				List<List<Curve>> list9 = new List<List<Curve>>();
				foreach (List<XYZ> list10 in list8)
				{
					List<Curve> list11 = new List<Curve>();
					for (int i = 0; i < list10.Count; i++)
					{
						int index = (i + 1) % list10.Count;
						XYZ xyz2 = new XYZ(list10[i].X, list10[i].Y, 0.0);
						XYZ xyz3 = new XYZ(list10[index].X, list10[index].Y, 0.0);
						Curve item = Line.CreateBound(xyz2, xyz3);
						list11.Add(item);
					}
					list9.Add(list11);
				}
				list7.Add(list9);
			}
			return list7;
		}

		private static List<XYZ> CompressPoints(PointF[] pts)
		{
			List<XYZ> list = new List<XYZ>();
			if (pts.Length > 1)
			{
				list.Add(new XYZ((double)pts[0].X, (double)pts[0].Y, 0.0));
				for (int i = 1; i < pts.Length; i++)
				{
					XYZ xyz = list[list.Count - 1];
					XYZ xyz2 = new XYZ((double)pts[i].X, (double)pts[i].Y, 0.0);
					if (xyz2.DistanceTo(xyz) >= 1E-10)
					{
						list.Add(xyz2);
					}
				}
			}
			return list;
		}

		private static List<ArrayArea> GetBelongArea(ref List<int> innerAreaIndex, List<ArrayArea> allArea, ArrayArea areaSelf)
		{
			List<ArrayArea> list = new List<ArrayArea>();
			int num = 0;
			for (int i = 0; i < allArea.Count; i++)
			{
				ArrayArea arrayArea = allArea[i];
				if (arrayArea.startPos > areaSelf.startPos && arrayArea.endPos < areaSelf.endPos)
				{
					innerAreaIndex.Add(i);
					bool flag = false;
					if (num == 0)
					{
						list.Add(allArea[i]);
					}
					else
					{
						for (int j = 0; j < list.Count; j++)
						{
							ArrayArea arrayArea2 = list[j];
							if (arrayArea2.startPos > arrayArea.startPos && arrayArea2.endPos < arrayArea.endPos)
							{
								list[j] = arrayArea;
							}
							else if (arrayArea2.startPos >= arrayArea.startPos || arrayArea2.endPos <= arrayArea.endPos)
							{
								flag = true;
							}
						}
						if (flag)
						{
							list.Add(arrayArea);
						}
					}
					num++;
				}
			}
			return list;
		}

		private static List<List<XYZ>> DivPoints(List<XYZ> outerAreaPts)
		{
			List<List<XYZ>> list = new List<List<XYZ>>();
			List<int> list2 = new List<int>();
			List<int> list3 = new List<int>();
			for (int i = 0; i < outerAreaPts.Count; i++)
			{
				int j = 0;
				while (j < outerAreaPts.Count)
				{
					if (i != j && outerAreaPts[i].DistanceTo(outerAreaPts[j]) < 1E-06)
					{
						if (list3.IndexOf(i) == -1 && list2.IndexOf(j) == -1)
						{
							list2.Add(i);
							list3.Add(j);
							break;
						}
						break;
					}
					else
					{
						j++;
					}
				}
			}
			List<ArrayArea> list4 = new List<ArrayArea>();
			for (int k = 0; k < list2.Count; k++)
			{
				list4.Add(new ArrayArea
				{
					startPos = list2[k],
					endPos = list3[k]
				});
			}
			List<int> list5 = new List<int>();
			for (int l = 0; l < list4.Count; l++)
			{
				List<XYZ> list6 = new List<XYZ>();
				for (int m = list4[l].startPos; m <= list4[l].endPos; m++)
				{
					list6.Add(outerAreaPts[m]);
				}
				new List<ArrayArea>();
				foreach (ArrayArea arrayArea in GpcPolygonController.GetBelongArea(ref list5, list4, list4[l]))
				{
					for (int n = arrayArea.startPos + 1; n <= arrayArea.endPos; n++)
					{
						XYZ xyz = outerAreaPts[n];
						for (int num = 0; num < list6.Count; num++)
						{
							if (list6[num].DistanceTo(xyz) < 1E-06)
							{
								list6.RemoveAt(num);
							}
						}
					}
				}
				list.Add(list6);
			}
			List<XYZ> list7 = new List<XYZ>();
			List<List<XYZ>> list8 = new List<List<XYZ>>();
			for (int num2 = 0; num2 < list.Count; num2++)
			{
				if (list5.IndexOf(num2) == -1)
				{
					list7.AddRange(list[num2]);
				}
				else
				{
					list8.Add(list[num2]);
				}
			}
			list8.Add(list7);
			return list8;
		}

		private static List<List<List<Curve>>> ConvertPointToAreaCurvesUseDiv(List<XPoint2D> pts)
		{
			List<List<XYZ>> list = GpcPolygonController.DivPoints(GpcPolygonController.CompressPoints(pts));
			List<List<List<XYZ>>> list2 = new List<List<List<XYZ>>>();
			foreach (List<XYZ> list3 in list)
			{
				List<XYZ> list4 = new List<XYZ>();
				List<List<XYZ>> list5 = new List<List<XYZ>>();
				foreach (XYZ xyz in list3)
				{
					if (GpcPolygonController.IsExistPoint(list4, xyz))
					{
						List<XYZ> list6 = GpcPolygonController.CompressPointForCurve(list4);
						if (list6.Count > 2)
						{
							list5.Add(list6);
						}
						list4 = new List<XYZ>();
					}
					else
					{
						list4.Add(xyz);
					}
				}
				list2.Add(list5);
			}
			List<List<List<Curve>>> list7 = new List<List<List<Curve>>>();
			foreach (List<List<XYZ>> list8 in list2)
			{
				List<List<Curve>> list9 = new List<List<Curve>>();
				foreach (List<XYZ> list10 in list8)
				{
					List<Curve> list11 = new List<Curve>();
					for (int i = 0; i < list10.Count; i++)
					{
						int index = (i + 1) % list10.Count;
						XYZ xyz2 = new XYZ(list10[i].X, list10[i].Y, 0.0);
						XYZ xyz3 = new XYZ(list10[index].X, list10[index].Y, 0.0);
						Curve item = Line.CreateBound(xyz2, xyz3);
						list11.Add(item);
					}
					list9.Add(list11);
				}
				list7.Add(list9);
			}
			return list7;
		}

		private static bool IsExistPoint(List<XYZ> pts, XYZ pt)
		{
			foreach (XYZ xyz in pts)
			{
				if (pt.IsAlmostEqualTo(xyz, 1E-10))
				{
					return true;
				}
			}
			return false;
		}

		private static List<XYZ> CompressPointForCurve(List<XYZ> arPt)
		{
			if (arPt.Count < 2)
			{
				return arPt;
			}
			List<XYZ> list = new List<XYZ>();
			for (int i = 0; i < arPt.Count; i++)
			{
				int index = (i + 1) % arPt.Count;
				XYZ xyz = new XYZ(arPt[i].X, arPt[i].Y, 0.0);
				XYZ xyz2 = new XYZ(arPt[index].X, arPt[index].Y, 0.0);
				if (xyz.DistanceTo(xyz2) >= UnitUtility.MMToFeet(0.8))
				{
					list.Add(xyz);
				}
			}
			List<XYZ> list2 = new List<XYZ>();
			int count = list.Count;
			for (int j = 0; j < count; j++)
			{
				XYZ xyz3 = list[j] - list[(j - 1 + count) % count];
				XYZ xyz4 = list[(j + 1) % count] - list[j];
				if (!xyz3.Normalize().IsAlmostEqualTo(xyz4.Normalize(), 1E-05))
				{
					list2.Add(list[j]);
				}
			}
			return list2;
		}

		private static List<XPoint2D> GetCurvePointsForGPC(List<Curve> lstInputCurves)
		{
			List<XPoint2D> list = new List<XPoint2D>();
			foreach (Curve curve in lstInputCurves)
			{
				IList<XYZ> list2 = curve.Tessellate();
				for (int i = 1; i < list2.Count; i++)
				{
					list.Add(new XPoint2D(list2[i].X, list2[i].Y));
				}
			}
			return list;
		}
	}
}
